
package com.tools.cleanmaster.controller;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;

import com.tools.cleanmaster.CleanApplication;
import com.tools.cleanmaster.appinfo.AppInfoSnapshot;
import com.tools.cleanmaster.appinfo.AppManager;
import com.tools.cleanmaster.model.TrashType;
import com.tools.cleanmaster.model.item.AppMemItem;
import com.tools.cleanmaster.model.item.TrashItem;
import com.tools.cleanmaster.store.GlobalConfigSharedPrefManager;
import com.tools.cleanmaster.utils.AppTaskUtils;
import com.tools.cleanmaster.utils.LogHelper;
import com.tools.cleanmaster.utils.MemoryUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class AppMemScanner extends TrashScanner {
    private final ActivityManager mAm;

    private static final int MEM_CLEAN_THRESHOLD = 5 * 60 * 1000;

    public AppMemScanner(Context context, TrashHandler handler) {
        super(context, handler);
        mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    }

    @Override
    public void scan(int increaseProgress) {
        mIsScanning = true;
        // Debug.startMethodTracing("trash_mem", 200 * 1024 * 1024);
        doScan(increaseProgress);
        // Debug.stopMethodTracing();
        mIsScanning = false;
    }

    private void doScan(int increaseProgress) {
        long startTime;
        startTime = System.currentTimeMillis();
        LogHelper.i(SUB_TAG, "AppMemScanner doScan increaseProgress=" + increaseProgress);
        if (mStopRequested) {
            return;
        }
        Map<String, Long> progressMem = getProgressesMem();
        if (mStopRequested) {
            return;
        }
        // 处理上次杀过的进程
        List<String> lastKilledPkgs = null;
        long totalSize = 0;
        long lastMemCleannedTime = GlobalConfigSharedPrefManager.getLastMemTrashCleanTime(mContext);
        if ((System.currentTimeMillis() - lastMemCleannedTime) < MEM_CLEAN_THRESHOLD) {
            lastKilledPkgs = GlobalConfigSharedPrefManager.getLastMemTrashCleanPkgs(mContext);
        }
        final int size = progressMem.size();
        int i = 0;
        for (String pkgName : progressMem.keySet()) {
            if (mStopRequested) {
                return;
            }
            int progress = calculateProgress(increaseProgress, i, size);
            i++;
            // 跳过白名单和上次杀过的进程
            if ((lastKilledPkgs != null && lastKilledPkgs.contains(pkgName))
                    || PKGS_WHITE_LIST.contains(pkgName)) {
                mTrashHandler.updateProgress(progress, null);
                continue;
            }
            AppInfoSnapshot appInfo = AppManager.getInstance(mContext).getAppInfo(pkgName);
            if (appInfo == null) {
                mTrashHandler.updateProgress(progress, null);
                continue;
            }
            mTrashHandler.updateProgress(progress, appInfo.getLabel());
            TrashItem trash = new AppMemItem(mContext);
            trash.trashType = TrashType.APP_MEM;
            trash.pkgName = pkgName;
            trash.appName = appInfo.getLabel();
            trash.size = progressMem.get(pkgName) * 1024;
            totalSize += trash.size;
            if (!mStopRequested) {
                mTrashesData.putTrash(TrashType.APP_MEM, trash);
            }
            LogHelper.i(SUB_TAG, "[trash_memory] appName:" + trash.appName + " size:"
                    + trash.size);
        }
        mTrashHandler.onTrashTypeFinish(TrashType.APP_MEM, totalSize);
        LogHelper.i(SUB_TAG, "AppMemScanner doScan end time="
                + (System.currentTimeMillis() - startTime));
    }

    private Map<String, Long> getProgressesMem() {
        Map<String, Long> pkgMemMap = new HashMap<String, Long>();
        Map<Integer, String> pidPkgMap = new HashMap<Integer, String>();//pid与pkgName的map
        // 先获取pid集合，再根据pid获取内存
        List<RunningAppProcessInfo> runProcessList = mAm.getRunningAppProcesses();
        if (runProcessList != null) {
            for (RunningAppProcessInfo amProcess : runProcessList) {
                String pkgName = AppTaskUtils.getPackageName(amProcess);
                if (!AppTaskUtils.checkRunningProcess(pkgName, amProcess.uid)) {
                    continue;
                }
                pidPkgMap.put(amProcess.pid, pkgName);
            }
        }

        List<RunningServiceInfo> runServiceList = mAm.getRunningServices(100);
        if (runServiceList != null) {
            for (RunningServiceInfo amService : runServiceList) {
                if (!amService.started || amService.restarting > 0) {
                    // Skip services which are not started or are restarting
                    continue;
                }
                String pkgName = amService.service.getPackageName();
                if (!AppTaskUtils.checkRunningProcess(pkgName, amService.uid)) {
                    continue;
                }
                pidPkgMap.put(amService.pid, pkgName);
            }
        }
        // 将pid转化为静态数组
        Set<Integer> pidsInteger = pidPkgMap.keySet();
        if (pidsInteger.isEmpty()) {
            return pkgMemMap;
        }
        int[] pids = new int[pidsInteger.size()];
        int index = 0;
        for (Integer pid : pidsInteger) {
            pids[index] = pid;
            index++;
        }
        // 获取内存
        int[] processMemUsage = MemoryUtils.getProcessMemUsage(CleanApplication.getInstance(), pids);
        for (int i = 0; i < processMemUsage.length; i++) {
            long size = processMemUsage[i];
            String pkgName = pidPkgMap.get(pids[i]);
            if (pkgMemMap.containsKey(pkgName)) {
                pkgMemMap.put(pkgName, pkgMemMap.get(pkgName) + size);
            } else {
                pkgMemMap.put(pkgName, size);
            }
        }
        return pkgMemMap;
    }

    private List<TrashItem> doScanSingle() {
        // TODO 还不需要使用
        long startTime = 0;
        LogHelper.i(SUB_TAG, "AppMemScanner doScanSingle finished! consume time=" + (System.currentTimeMillis() - startTime));
        List<TrashItem> memTrashItems = new ArrayList<TrashItem>();
        return memTrashItems;
    }

}
